using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using StudentBackendService.Filters;
using StudentBackendService.Mappers;
using StudentBackendService.Services;
using StudentBackendService.Services.v1;

namespace StudentBackendService
{
    public class BackendService
    {
        private readonly WebApplicationBuilder _builder;
        private WebApplication? _application;
        private readonly IConfiguration _configuration;
        private readonly IServiceCollection _services;
        private readonly IWebHostEnvironment _env;

        public BackendService(string[] args) 
        {
            _builder = WebApplication.CreateBuilder(args);
            _configuration = _builder.Configuration;
            _services = _builder.Services;
            _env = _builder.Environment;
        }

        public BackendService Configure()
        {
            ConfigureServices();
            _application = _builder.Build();
            ConfigureApplication();
            return this;
        }

        public void Run()
        {
            _application?.Run();
        }

        private void ConfigureServices()
        {
            _services.AddControllers(options => options.Filters.Add<ExceptionFilter>());
            _services.AddEndpointsApiExplorer();

            // 此处仅做注入
            _services.AddDbContext<SchoolContext>(opts => opts.UseNpgsql());

            // 用于启用或禁用 Npgsql 客户端与 Postgres 服务器之间的时间戳行为。
            AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
            AppContext.SetSwitch("Npgsql.DisableDateTimeInfinityConversions", true);

            // DI
            _services.AddScoped<IStudentManage, StudentManage>();

            // Swagger 注入
            _services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo
                {
                    Title = _configuration["application:name"],
                    Description = _configuration["application:description"],
                    Version = _configuration["application:version"]
                });
            });
        }

        private void ConfigureApplication()
        {
            if (_application is null)
                throw new InvalidOperationException();

            if (_env.IsDevelopment())
            {
                _application.UseSwagger();
                _application.UseSwaggerUI(c =>
                {
                    c.SwaggerEndpoint(_configuration["application:swagger:path"], $"{_configuration["application:swagger:description"]} {_configuration["application:version"]}");
                });
                _application.UseDeveloperExceptionPage();
            }
            _application.UseAuthorization();
            _application.MapControllers();
        }
    }
}